home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / REALITY / distort / rubber.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  285 lines

  1. /*
  2.  * Copyright 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.     rubber.c
  19.     Drew Olbrich, 1992
  20. */
  21.  
  22. #include <stdio.h>
  23. #include <math.h>
  24. #include <gl.h>
  25. #include <device.h>
  26.  
  27. #include "defs.h"
  28. #include "rubber.h"
  29.  
  30. EFFECT rubber = { rubber_init, rubber_dynamics, rubber_redraw, rubber_click };
  31.  
  32. #define SPRING_KS  0.3
  33. #define DRAG       0.5
  34.  
  35. typedef struct {
  36.   float x[3];
  37.   float v[3];
  38.   float t[2];
  39.   int nail;
  40. } MASS;
  41.  
  42. typedef struct {
  43.   int i, j;
  44.   float r;
  45. } SPRING;
  46.  
  47. static int spring_count;
  48.  
  49. static MASS *mass = NULL;
  50. static SPRING *spring = NULL;
  51.  
  52. static int grab = -1;    /* index of grabbed mass point */
  53.  
  54. void rubber_init()
  55. {
  56.   int i, j;
  57.   int k;
  58.   int m;
  59.  
  60.   zbuffer(TRUE);
  61.  
  62.   if (mass == NULL)
  63.   {
  64.     mass = (MASS *) malloc(sizeof(MASS)*GRID_SIZE_X*GRID_SIZE_Y);
  65.     if (mass == NULL)
  66.     {
  67.       fprintf(stderr, "rubber: Can't allocate memory.\n");    
  68.       exit(-1);
  69.     }
  70.   }
  71.  
  72.   k = 0;
  73.   for (i = 0; i < GRID_SIZE_X; i++)
  74.     for (j = 0; j < GRID_SIZE_Y; j++)
  75.     {
  76.       mass[k].nail = (i == 0 || j == 0 || i == GRID_SIZE_X - 1
  77.               || j == GRID_SIZE_Y - 1);
  78.       mass[k].x[0] = i/(GRID_SIZE_X - 1.0)*WIN_SIZE_X;
  79.       mass[k].x[1] = j/(GRID_SIZE_Y - 1.0)*WIN_SIZE_Y;
  80.       mass[k].x[2] = -(CLIP_FAR - CLIP_NEAR)/2.0;
  81.  
  82.       mass[k].v[0] = 0.0;
  83.       mass[k].v[1] = 0.0;
  84.       mass[k].v[2] = 0.0;
  85.  
  86.       mass[k].t[0] = i/(GRID_SIZE_X - 1.0);
  87.       mass[k].t[1] = j/(GRID_SIZE_Y - 1.0);
  88.  
  89.       k++;
  90.     }
  91.  
  92.   if (spring == NULL)
  93.   {
  94.     spring_count = (GRID_SIZE_X - 1)*(GRID_SIZE_Y - 2)
  95.       + (GRID_SIZE_Y - 1)*(GRID_SIZE_X - 2);
  96.     
  97.     spring = (SPRING *) malloc(sizeof(SPRING)*spring_count);
  98.     if (spring == NULL)
  99.     {
  100.       fprintf(stderr, "rubber: Can't allocate memory.\n");    
  101.       exit(-1);
  102.     }
  103.   }
  104.  
  105.   k = 0;
  106.   for (i = 1; i < GRID_SIZE_X - 1; i++)
  107.     for (j = 0; j < GRID_SIZE_Y - 1; j++)
  108.     {
  109.       m = GRID_SIZE_Y*i + j;
  110.       spring[k].i = m;
  111.       spring[k].j = m + 1;
  112.       spring[k].r = (WIN_SIZE_Y - 1.0)/(GRID_SIZE_Y - 1.0);
  113.       k++;
  114.     }
  115.  
  116.   for (j = 1; j < GRID_SIZE_Y - 1; j++)
  117.     for (i = 0; i < GRID_SIZE_X - 1; i++)
  118.     {
  119.       m = GRID_SIZE_Y*i + j;
  120.       spring[k].i = m;
  121.       spring[k].j = m + GRID_SIZE_X;
  122.       spring[k].r = (WIN_SIZE_X - 1.0)/(GRID_SIZE_X - 1.0);
  123.       k++;
  124.     }
  125. }
  126.  
  127. /*
  128.     Do the dynamics simulation for the next frame.
  129. */
  130.  
  131. void rubber_dynamics(int mousex, int mousey)
  132. {
  133.   int k;
  134.   float d[3];
  135.   int i, j;
  136.   float l;
  137.   float a;
  138.  
  139.   /* calculate all the spring forces acting on the mass points */
  140.  
  141.   for (k = 0; k < spring_count; k++)
  142.   {
  143.     i = spring[k].i;
  144.     j = spring[k].j;
  145.  
  146.     d[0] = mass[i].x[0] - mass[j].x[0];
  147.     d[1] = mass[i].x[1] - mass[j].x[1];
  148.     d[2] = mass[i].x[2] - mass[j].x[2];
  149.  
  150.     l = sqrt(d[0]*d[0] + d[1]*d[1] + d[2]*d[2]);
  151.  
  152.     if (l != 0.0)
  153.     {
  154.       d[0] /= l;
  155.       d[1] /= l;
  156.       d[2] /= l;
  157.  
  158.       a = l - spring[k].r;
  159.  
  160.       mass[i].v[0] -= d[0]*a*SPRING_KS;
  161.       mass[i].v[1] -= d[1]*a*SPRING_KS;
  162.       mass[i].v[2] -= d[2]*a*SPRING_KS;
  163.  
  164.       mass[j].v[0] += d[0]*a*SPRING_KS;
  165.       mass[j].v[1] += d[1]*a*SPRING_KS;
  166.       mass[j].v[2] += d[2]*a*SPRING_KS;
  167.     }
  168.   }
  169.  
  170.   /* update the state of the mass points */
  171.  
  172.   for (k = 0; k < GRID_SIZE_X*GRID_SIZE_Y; k++)
  173.     if (!mass[k].nail)
  174.     {
  175.       mass[k].x[0] += mass[k].v[0];
  176.       mass[k].x[1] += mass[k].v[1];
  177.       mass[k].x[2] += mass[k].v[2];
  178.       
  179.       mass[k].v[0] *= (1.0 - DRAG);
  180.       mass[k].v[1] *= (1.0 - DRAG);
  181.       mass[k].v[2] *= (1.0 - DRAG);
  182.  
  183.       if (mass[k].x[2] > -CLIP_NEAR - 0.01)
  184.     mass[k].x[2] = -CLIP_NEAR - 0.01;
  185.       if (mass[k].x[2] < -CLIP_FAR + 0.01)
  186.     mass[k].x[2] = -CLIP_FAR + 0.01;
  187.     }
  188.  
  189.   /* if a mass point is grabbed, attach it to the mouse */
  190.  
  191.   if (grab != -1 && !mass[grab].nail)
  192.   {
  193.     mass[grab].x[0] = mousex;
  194.     mass[grab].x[1] = mousey;
  195.     mass[grab].x[2] = -(CLIP_FAR - CLIP_NEAR)/4.0;
  196.   }
  197. }
  198.  
  199. /*
  200.     Draw the next frame of animation.
  201. */
  202.  
  203. void rubber_redraw()
  204. {
  205.   int k;
  206.   int i, j;
  207.  
  208.   zclear();
  209.  
  210.   cpack(0xFFFFFFFF);
  211.  
  212. #define _WIREFRAME
  213. #ifdef WIREFRAME
  214.   for (k = 0; k < spring_count; k++)
  215.   {
  216.     bgnline();
  217.     v3f(mass[spring[k].i].x);
  218.     v3f(mass[spring[k].j].x);
  219.     endline();
  220.   }
  221. #else
  222.   k = 0;
  223.   for (i = 0; i < GRID_SIZE_X - 1; i++)
  224.   {
  225.     for (j = 0; j < GRID_SIZE_Y - 1; j++)
  226.     {
  227.       bgnpolygon();
  228.       t2f(mass[k].t);
  229.       v3f(mass[k].x);
  230.       t2f(mass[k + 1].t);
  231.       v3f(mass[k + 1].x);
  232.       t2f(mass[k + GRID_SIZE_Y + 1].t);
  233.       v3f(mass[k + GRID_SIZE_Y + 1].x);
  234.       t2f(mass[k + GRID_SIZE_Y].t);
  235.       v3f(mass[k + GRID_SIZE_Y].x);
  236.       endpolygon();
  237.       k++;
  238.     }
  239.     k++;
  240.   }
  241. #endif
  242.  
  243.   swapbuffers();
  244. }
  245.  
  246. /*
  247.     Return the index of the mass point that's nearest to the
  248.     given screen coordinate.
  249. */
  250.  
  251. int rubber_grab(int x, int y)
  252. {
  253.   float dx[2];
  254.   float d;
  255.   float min_d;
  256.   float min_i;
  257.   int i;
  258.  
  259.   for (i = 0; i < GRID_SIZE_X*GRID_SIZE_Y; i++)
  260.   {
  261.     dx[0] = mass[i].x[0] - x;
  262.     dx[1] = mass[i].x[1] - y;
  263.     d = sqrt(dx[0]*dx[0] + dx[1]*dx[1]);
  264.     if (i == 0 || d < min_d)
  265.     {
  266.       min_i = i;
  267.       min_d = d;
  268.     }
  269.   }
  270.  
  271.   return min_i;
  272. }
  273.  
  274. /*
  275.     If the mouse is pressed down, grab the nearest mass point.
  276. */
  277.  
  278. void rubber_click(int mousex, int mousey, int state)
  279. {
  280.   if (state)
  281.     grab = rubber_grab(mousex, mousey);
  282.   else
  283.     grab = -1;
  284. }
  285.